<?php

namespace app\common\model\mycurrency;

use app\common\library\device\cabinet\Analysis;
use app\common\library\device\cabinet\Control;
use think\Exception;
use think\Model;
use think\Queue;
use traits\model\SoftDelete;
use think\Db;

class LeaseOrderDevice extends Model
{

    //use SoftDelete;

    // 表名
    protected $name = 'mycurrency_lease_order_device';

    // 追加属性
    protected $append = [
        'detection_door_status_text',
        'detection_block_status_text',
        'detection_infrared_status_text',
    ];

    const STATUS_QUXIAO = -1;//状态:-1=取消
    const STATUS_WEIZULIN = 1;//状态:1=未租赁
    const STATUS_ZULINZHONG = 2;//状态:2=租赁中
    const STATUS_SHIYONGZHONG = 3;//状态:3=使用中
    const STATUS_GUIHUANZHONG = 4;//状态:4=归还中
    const STATUS_JIANCEZHONG = 5;//状态:5=检测中
    const STATUS_YIGUIHUAN = 6;//状态:5=已归还

    const RETURN_TYPE_GUIHUAN = 1;//设备归还类型（比如换电柜可能用到这个字段，还会结束订单，换不回结束订单）:1=还
    const RETURN_TYPE_GEGNHUAN = 2;//设备归还类型（比如换电柜可能用到这个字段，还会结束订单，换不回结束订单）:2=换

    const DETECTION_DOOR_STATUS_WEIGUANMEN = -1;//归还检测-门状态检测:-1=检测到未关门
    const DETECTION_DOOR_STATUS_WEIJIANCE = 1;//归还检测-门状态检测:1=未检测
    const DETECTION_DOOR_STATUS_JIANCEZHONG = 2;//归还检测-门状态检测:2=检测中
    const DETECTION_DOOR_STATUS_YITONGGUO = 3;//归还检测-门状态检测:3=已通过【检测到已关门】

    const DETECTION_BLOCK_STATUS_WUKA = -1;//归还检测-sd卡检测状态:-1=未检测到sd卡
    const DETECTION_BLOCK_STATUS_KACUOWU = -2;//归还检测-sd卡检测状态:-2=检测到错误的sd卡
    const DETECTION_BLOCK_STATUS_WEIJIANCE = 1;//归还检测-sd卡检测状态:1=未检测
    const DETECTION_BLOCK_STATUS_JIANCEZHONG = 2;//归还检测-sd卡检测状态:2=检测中
    const DETECTION_BLOCK_STATUS_YITONGGUO = 3;//归还检测-sd卡检测状态:3=已通过【检测到正确的sd卡号】

    const DETECTION_INFRARED_STATUS_WEIZHEDANG = -1;//归还检测-红外检测状态:-1=未检测到红外遮挡
    const DETECTION_INFRARED_STATUS_WEIJIANCE = 1;//归还检测-红外检测状态:1=未检测
    const DETECTION_INFRARED_STATUS_JIANCEZHONG = 2;//归还检测-红外检测状态:2=检测中
    const DETECTION_INFRARED_STATUS_YITONGGUO = 3;//归还检测-红外检测状态:3=已通过【检测到红外已遮挡】

    const DETECTION_TYPE_door = 1;//检测类型 1 门检测
    const DETECTION_TYPE_block = 2;//检测类型 2 卡id检测
    const DETECTION_TYPE_infrared = 3;//检测类型 3 红外检测

    const RETURN_OPEN_PROGRESS_KAIMENSHIBAI = -1;//租赁归还开门进度:-1=开门失败
    const RETURN_OPEN_PROGRESS_KAIMENZHONG = 1;//租赁归还开门进度:1=开门中
    const RETURN_OPEN_PROGRESS_YIKAIMEN = 2;//租赁归还开门进度:2=已开门

    /**
     * 添加设备使用记录
     * @param int $lease_order_id 租赁订单id
     * @param int $device_id 设备id
     * @param int $device_lattice_id 设备格口id
     * @param int $user_id 用户id
     */
    public static function deviceAdd($lease_order_id,$device_id,$device_lattice_id,$user_id = null){
        if(!$user_id){
            $user_id = LeaseOrder::where(['id' => $lease_order_id])->value('user_id');
        }
        //添加设备使用记录
        $device_increase = [
            'lease_order_id' => $lease_order_id,
            'user_id' => $user_id,
            'device_id' =>$device_id,
            'status' => self::STATUS_WEIZULIN,
            'createtime' => time(),
            'device_lattice_id' => $device_lattice_id,
        ];
        $order_device = self::create($device_increase);

        //修改设备状态
        DeviceLattice::where(['id' => $device_lattice_id])->update([
            'use_status' => DeviceLattice::USE_STATUS_WUGAN,
        ]);

        return $order_device;
    }

    /**
     * 设备弹出结果通知
     * 说明 ： 开锁指令后 设备上报打开成功 设备上报打开失败 设备长时间未上报打开结果【视为打开失败】 调用该方法处理租赁订单
     * @param int $lease_order_device_id 租赁带单设备租赁记录id
     * @param int $device_result 打开结果
     */
    public static function deviceOpenResult($lease_order_device_id,$device_result){
        trace('========================开始处理租赁逻辑2==============================' . $lease_order_device_id . '================' .$device_result);
        $order_device = self::get($lease_order_device_id);
        trace([$order_device]);
        if(!$order_device){
            trace('========================开始处理租赁逻辑3==============================租赁订单记录不存在');
            throw new Exception('租赁订单设备使用记录不存在');
            return false;
        }
        if ($order_device['status'] != LeaseOrderDevice::STATUS_ZULINZHONG){
            trace('========================开始处理租赁逻辑4==============================非租赁中状态');
            throw new Exception('非租赁中状态');
            return false;
        }
        $result = 1;//打开结果 1 打开成功 2 打开失败
        $fail_type = 0;//失败原因
        if ($order_device){
            $result = $device_result == 0 ? 1 : 2;
        }
        if ($device_result != 0){
            //2=缺货,3=开门失败,4=销售订单号重复
            switch ($device_result) {
                case 1://缺货
                    $fail_type = 2;
                    break;
                case 2://开门失败
                    $fail_type = 3;
                    break;
                case 5://销售订单号重复
                    $fail_type = 4;
                    break;
                default:
                    break;
            }
        }
        LeaseOrder::orderStartRentingResult($order_device->id,$result,$fail_type);
    }

    /**
     * 设备归还
     * @param int $device_lattice_id 设备格口id
     * @param int $result 归还结果 0 成功，关门设备已归还/充电 1 超时门未关闭
     * @param string $use_end_time 结束时间
     */
    public static function deviceReturn($device_lattice_id,$result,$use_end_time = null){
        if ($use_end_time == null){
            $use_end_time = time();
        }
        trace('========================开始处理结束订单5==============================设备格口id：' . $device_lattice_id . '=================执行结果：' . $result);
        $order_device_id = null;
        trace('========================开始处理结束订单5-1 查询设备使用记录==============================设备格口id：' . $device_lattice_id);
        //查询租赁订单设备租赁信息
        $order_device = self::where([
            'device_lattice_id' => $device_lattice_id,
            'status' => ['in',[
                self::STATUS_SHIYONGZHONG,
                self::STATUS_GUIHUANZHONG,
            ]],
            'deletetime' => null,
        ])
            ->order('id desc')
            ->find();
        trace('========================开始处理结束订单6 查询出设备租赁信息==============================' . json_encode($order_device));
        if($order_device){//有进行中的租赁订单设备使用记录
            trace('========================开始处理结束订单7==============================');
            //关门成功
            if ($result == 0 || $result == 2 || $result == 3){
                trace('========================开始处理结束订单8 关门成功==============================');
                trace('========================开始处理结束订单8-1 订单设备使用记录状态==============================结束时间' . date('Y-m-d H:i:s',$use_end_time));
                //修改租赁订单设备租赁状态
                $order_device->use_end_time = $use_end_time;//归还时间
                $order_device->status = self::STATUS_JIANCEZHONG;//状态 检测中
                $order_device->save();
                trace('========================开始处理结束订单8-2 修改完订单设备使用状态==============================');
                if ($order_device->return_type == self::RETURN_TYPE_GUIHUAN){//还设备
                    //开始检测流程
                    $queue_default = config('queue.default');
                    Queue::later(1, "app\common\job\Lease@detectionSending", ['detection_type' => self::DETECTION_TYPE_door,'order_device_id'=>$order_device->id], $queue_default);
                }elseif ($order_device->return_type == self::RETURN_TYPE_GEGNHUAN){//换设备：主要应用场景在换电柜，目前暂不实现该逻辑，后期可能应用场景比如说设备在租赁后出现故障有平台工作人员给客户换设备

                }
            }
            //关门超时
            elseif ($result == 1){
                //添加定时任务
                trace('========================开始处理结束订单8-6 关门超时添加定时任务查询隔扣状态==============================' . $order_device['id']);
                $queue_default = config('queue.default');
                Queue::later(10, "addons\mycurrency\controller\job\Lease@returnInspect", ['lease_order_device_id' => $order_device['id']], $queue_default);
            }
            //已关门，设备未检测到归位/充电 or 已关门，设备未检测到正确物品
            elseif ($result == 2 || $result == 3){
                //取消归还 继续使用
                trace('========================开始处理结束订单8-6 已经关门无杆 继续使用==============================');
                LeaseOrder::orderContinuedUse($order_device->id);
            }
            return $order_device->id;
        }
        return null;
    }

    /**
     * 归还检测 - 发送检测指令
     * 说明 包括 查询们状态 查询卡id 查询红外遮挡
     * @param int $detection_type 检测类型 1 门检测 2 卡id检测 3 红外检测
     * @param int $order_device_id 设备租赁记录id
     */
    public static function detectionSending($detection_type,$order_device_id){
        $order_device = self::where(['id' => $order_device_id,'deletetime' => null])->find();
        if (!$order_device){
            throw new Exception("租赁订单设备使用记录不存在:{$order_device_id}");
            return false;
        }
        if ($order_device->status != self::STATUS_JIANCEZHONG){
            throw new Exception("非检测中状态");
            return false;
        }
        if ($detection_type == self::DETECTION_TYPE_block || $detection_type == self::DETECTION_TYPE_infrared){//检测类型 2 卡id检测 3 红外检测  只有检测到们关闭后 才能检测卡id 及 红外遮挡
            if($order_device->detection_door_status != self::DETECTION_DOOR_STATUS_YITONGGUO){
                throw new Exception("门检测状态未通过，只有门状态检测通过后才可以检测卡id及红外遮挡");
                return false;
            }
        }
        //查询柜子格口信息
        $device_lattice = DeviceLattice::get($order_device->device_lattice_id);
        if ($detection_type == self::DETECTION_TYPE_door){//门检测
            $data = "{$device_lattice['number']}";
            Control::sending(
                $order_device->device_id,
                Analysis::CODE_CHAXUNZHUANGTAI,
                $data,
                [
                    'device_lattice_id' => $device_lattice->id,//柜门id
                    'control_type' => DeviceInstruction::CONTROL_TYPE_GUIHUANJIANCEMENSHIFOUGUANBI,//控制类型 = 归还检测流程查询门是否关闭
                    'lease_order_device_id' => $order_device->id,//用户租赁订单设备使用记录表id
                ]
            );
            $order_device->detection_door_status = self::DETECTION_DOOR_STATUS_JIANCEZHONG;
            $order_device->save();
        }elseif ($detection_type == self::DETECTION_TYPE_block){//卡id检测
            $data = "{$device_lattice['number']}";
            Control::sending(
                $order_device->device_id,
                Analysis::CODE_BUKA,
                $data,
                [
                    'device_lattice_id' => $device_lattice->id,//柜门id
                    'control_type' => DeviceInstruction::CONTROL_TYPE_GUIHUANJIANCEKAID,//控制类型 = 归还检测流程查询杆子卡id
                    'lease_order_device_id' => $order_device->id,//用户租赁订单设备使用记录表id
                ]
            );
            $order_device->detection_block_status = self::DETECTION_BLOCK_STATUS_JIANCEZHONG;
            $order_device->save();
        }elseif ($detection_type == self::DETECTION_TYPE_infrared){//红外遮挡检测
            $data = "{$device_lattice['number']}";
            Control::sending(
                $order_device->device_id,
                Analysis::CODE_CHAXUNCHUANGANQI,
                $data,
                [
                    'device_lattice_id' => $device_lattice->id,//柜门id
                    'control_type' => DeviceInstruction::CONTROL_TYPE_GUIHUANLIUCHENGJIANCEHONGWAIZHEDANGQINGKUANG,//控制类型 = 归还检测流程查询红外遮挡情况
                    'lease_order_device_id' => $order_device->id,//用户租赁订单设备使用记录表id
                ]
            );
            $order_device->detection_infrared_status = self::DETECTION_INFRARED_STATUS_JIANCEZHONG;
            $order_device->save();
        }
    }


    /**
     * 归还检测 - 设备上报检测结果处理
     * 说明 包括 查询们状态应答 查询卡id应答 查询红外遮挡应答
     * @param int $detection_type 检测类型 1 门检测 2 卡id检测 3 红外检测
     * @param int $order_device_id 设备租赁记录id
     * @param array $message 设备上报消息
     */
    public static function detectionResponse($detection_type,$order_device_id,$message){
        $order_device = self::where(['id' => $order_device_id,'deletetime' => null])->find();
        if (!$order_device){
            throw new Exception("租赁订单设备使用记录不存在:{$order_device_id}");
            return false;
        }
        if ($detection_type == self::DETECTION_TYPE_door){//门检测
            //修改门检测状态
            if ($message['message']['state_str'] == 0 || $message['message']['state_str'] == 2 || $message['message']['state_str'] == 3){//门已经关闭
                $order_device->detection_door_status = self::DETECTION_DOOR_STATUS_YITONGGUO;
            }elseif ($message['message']['state_str'] == 1){//门未关闭
                $order_device->detection_door_status = self::DETECTION_DOOR_STATUS_WEIGUANMEN;
            }
            $order_device->save();
            if ($message['message']['state_str'] == 0 || $message['message']['state_str'] == 2 || $message['message']['state_str'] == 3){//门关闭成功后 检测卡id是否正确
                //开始进行卡id检测
                $queue_default = config('queue.default');
                Queue::later(1, "app\common\job\Lease@detectionSending", ['detection_type' => self::DETECTION_TYPE_block,'order_device_id'=>$order_device->id], $queue_default);
            }
        }elseif ($detection_type == self::DETECTION_TYPE_block){//卡id检测
            if ($order_device->block_id != null){
                //修改卡id检测状态
                if ($message['message']['card_number_1'] == "NULL"){//未读取到杆子卡号
                    $order_device->detection_block_status = self::DETECTION_BLOCK_STATUS_WUKA;
                }elseif ($message['message']['card_number_1'] != $order_device->block_id){//读取到个杆子id号跟借用时候读取的杆子id号不一致
                    $order_device->detection_block_status = self::DETECTION_BLOCK_STATUS_KACUOWU;
                }elseif ($message['message']['card_number_1'] != "NULL" && $message['message']['card_number_1'] == $order_device->block_id){//读取到了杆子的id号 并且与借用时候的一致
                    $order_device->detection_block_status = self::DETECTION_BLOCK_STATUS_YITONGGUO;
                }
            }else{
                $order_device->detection_block_status = self::DETECTION_BLOCK_STATUS_YITONGGUO;
            }
            $order_device->save();

            //判断是否需要检测红外
            $device = Device::where(['id' => $order_device->device_id])->find();
            if ($device->is_infra_red == Device::IS_INFRA_RED_YOU){//需要检测红外
                //if ($message['message']['card_number_1'] != "NULL" && $message['message']['card_number_1'] == $order_device->block_id){//读取到了杆子的id号 并且与借用时候的一致
                //开始进行红外遮挡检测
                $queue_default = config('queue.default');
                Queue::later(1, "app\common\job\Lease@detectionSending", ['detection_type' => self::DETECTION_TYPE_infrared,'order_device_id'=>$order_device->id], $queue_default);
                //}
            }elseif ($device->is_infra_red == Device::IS_INFRA_RED_WU){//不需要检测红外
                //归还检测-门状态检测:3=已通过【检测到已关门】&& 归还检测-sd卡检测状态:3=已通过【检测到正确的sd卡号】
                if ($order_device->detection_door_status == self::DETECTION_DOOR_STATUS_YITONGGUO && $order_device->detection_block_status == self::DETECTION_BLOCK_STATUS_YITONGGUO){
                    self::returnDetectionComplete($order_device->id);
                }
            }
        }elseif ($detection_type == self::DETECTION_TYPE_infrared){//红外遮挡检测
            //修改红外检测状态
            if ($message['message']['cabinet_state_1'] == 1){//没有遮挡
                $order_device->detection_infrared_status = self::DETECTION_INFRARED_STATUS_WEIZHEDANG;
            }elseif ($message['message']['cabinet_state_1'] == 0){//有遮挡
                $order_device->detection_infrared_status = self::DETECTION_INFRARED_STATUS_YITONGGUO;
            }
            $order_device->save();
            if ($message['message']['cabinet_state_1'] == 0){//有遮挡
                //归还检测-门状态检测:3=已通过【检测到已关门】&& 归还检测-sd卡检测状态:3=已通过【检测到正确的sd卡号】
                if ($order_device->detection_door_status == self::DETECTION_DOOR_STATUS_YITONGGUO && $order_device->detection_block_status == self::DETECTION_BLOCK_STATUS_YITONGGUO && $order_device->detection_infrared_status == self::DETECTION_INFRARED_STATUS_YITONGGUO){
                    self::returnDetectionComplete($order_device->id);
                }
            }
        }
        return $order_device->id;
    }

    /**
     * 归还检测完成
     * @param int $order_device_id 设备使用记录id
     */
    public static function returnDetectionComplete($order_device_id){
        $order_device = self::where(['id' => $order_device_id,'deletetime' => null])->find();
        if (!$order_device){
            throw new Exception("租赁订单设备使用记录不存在1:{$order_device_id}");
            return false;
        }
        //结束订单
        trace(["27========================处理lease_order_id报错问题_returnDetectionComplete==============================" => $order_device],'error');
        trace('========================开始处理结束订单8-3 开始执行主订单的结束==============================租赁订单id：' . $order_device->lease_order_id);

        LeaseOrder::orderEnd($order_device->lease_order_id,time());
        trace('========================开始处理结束订单8-4 订单结束逻辑处理完成==============================');
        //LeaseOrder::orderEndAfter($order_device->lease_order_id);

        trace('========================开始处理结束订单8-5 修改格扣状态==============================' . $order_device->device_lattice_id);
        //$order_device_id = $order_device->id;

        //修改租赁订单个口状态
        $order_device->status = self::STATUS_YIGUIHUAN;
        $order_device->save();

        //修改隔扣状态为有杆
        DeviceLattice::where(['id' => $order_device->device_lattice_id])->update([
            'use_status' => DeviceLattice::USE_STATUS_YOUGAN,
        ]);
        trace('========================开始处理结束订单8-5 修改隔扣状态完成==============================');
    }

    /**
     * 归还检测-门状态检测:-1=检测到未关门,1=未检测,2=检测中,3=已通过【检测到已关门】  detection_door_status_text
     */
    public function getDetectionDoorStatusTextAttr($value, $data)
    {
        $str = '';
        switch ($data['detection_door_status']) {
            case self::DETECTION_DOOR_STATUS_WEIGUANMEN://-1=检测到未关门
                $str = '检测到门未关闭';
                break;
            case self::DETECTION_DOOR_STATUS_WEIJIANCE://1=未检测
                $str = '准备检测中';
                break;
            case self::DETECTION_DOOR_STATUS_JIANCEZHONG://2=检测中
                $str = '检测中';
                break;
            case self::DETECTION_DOOR_STATUS_YITONGGUO://3=已通过【检测到已关门】
                $str = '已关门';
                break;
            default:
                break;
        }
        return $str;
    }

    /**
     * 归还检测-sd卡检测状态:-1=未检测到sd卡,-2=检测到错误的sd卡,1=未检测,2=检测中,3=已通过【检测到正确的sd卡号】  detection_block_status_text
     */
    public function getDetectionBlockStatusTextAttr($value, $data)
    {
        $str = '';
        switch ($data['detection_block_status']) {
            case self::DETECTION_BLOCK_STATUS_WUKA://-1=未检测到sd卡
                $str = '未检测到NFC卡号';
                break;
            case self::DETECTION_BLOCK_STATUS_KACUOWU://-2=检测到错误的sd卡
                $str = '检测到的NFC卡号错误';
                break;
            case self::DETECTION_BLOCK_STATUS_WEIJIANCE://1=未检测
                $str = '准备检测中';
                break;
            case self::DETECTION_BLOCK_STATUS_JIANCEZHONG://2=检测中
                $str = '检测中';
                break;
            case self::DETECTION_BLOCK_STATUS_YITONGGUO://3=已通过【检测到正确的sd卡号】
                $str = '已通过';
                break;
            default:
                break;
        }
        return $str;
    }

    /**
     * 归还检测-红外检测状态:-1=未检测到红外遮挡,1=未检测,2=检测中,3=已通过【检测到红外已遮挡】  detection_infrared_status_text
     */
    public function getDetectionInfraredStatusTextAttr($value, $data)
    {
        $str = '';
        switch ($data['detection_infrared_status']) {
            case self::DETECTION_INFRARED_STATUS_WEIZHEDANG://-1=未检测到红外遮挡
                $str = '未检测到红外遮挡';
                break;
            case self::DETECTION_INFRARED_STATUS_WEIJIANCE://1=未检测
                $str = '准备检测中';
                break;
            case self::DETECTION_INFRARED_STATUS_JIANCEZHONG://2=检测中
                $str = '检测中';
                break;
            case self::DETECTION_INFRARED_STATUS_YITONGGUO://3=已通过【检测到红外已遮挡】
                $str = '已通过';
                break;
            default:
                break;
        }
        return $str;
    }

    public function device(){
        return $this->hasOne(Device::class, 'id', 'device_id');
    }

    public function lattice(){
        return $this->hasOne(DeviceLattice::class, 'id', 'device_lattice_id');
    }


}
